﻿using DrawableObjects.Actors;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System;
using Microsoft.Xna.Framework;
using DrawableObjects.Actors.Aircrafts;
using DrawableObjects.Actors.Aircrafts.Controller;
using DrawableObjects.Actors.Weapons;
using GlobalGameClasses;
using Serialization;
using Sirian.DrawableObject.Actors;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Audio;
using System.IO;

namespace InSovietRussiaProgrammTestsYou
{
    /// <summary>
    ///Dies ist eine Testklasse für "ActorTest" und soll
    ///alle ActorTest Komponententests enthalten.
    ///</summary>
    [TestClass()]
    public class AIControlledAircraft_DroneTest
    {
        private TestContext testContextInstance;

        /// <summary>
        ///Ruft den Testkontext auf, der Informationen
        ///über und Funktionalität für den aktuellen Testlauf bietet, oder legt diesen fest.
        ///</summary>
        public TestContext TestContext
        {
            get
            {
                return testContextInstance;
            }
            set
            {
                testContextInstance = value;
            }
        }

        #region Zusätzliche Testattribute
        // 
        //Sie können beim Verfassen Ihrer Tests die folgenden zusätzlichen Attribute verwenden:
        //
        //Mit ClassInitialize führen Sie Code aus, bevor Sie den ersten Test in der Klasse ausführen.
        //[ClassInitialize()]
        //public static void MyClassInitialize(TestContext testContext)
        //{
        //}
        //
        //Mit ClassCleanup führen Sie Code aus, nachdem alle Tests in einer Klasse ausgeführt wurden.
        //[ClassCleanup()]
        //public static void MyClassCleanup()
        //{
        //}
        //
        //Mit TestInitialize können Sie vor jedem einzelnen Test Code ausführen.
        [TestInitialize()]
        public void MyTestInitialize()
        {
            System.Windows.Forms.Form form = new System.Windows.Forms.Form();
            form.Visible = false;
            form.ShowInTaskbar = false;
            PresentationParameters param = new PresentationParameters();
            param.DeviceWindowHandle = form.Handle;
            param.IsFullScreen = false;
            GraphicsDevice device = new GraphicsDevice(GraphicsAdapter.DefaultAdapter, GraphicsProfile.Reach, param);
            GlobalGameClasses.GlobalGameValues.Values.graphicsDevice = device;
            GlobalGameClasses.GlobalGameValues.Values.spriteBatch = new SpriteBatch(device);
            GlobalGameValues.Values.content.addTexture("item_Laser", new Texture2D(device, 1, 1));
            GlobalGameValues.Values.content.addContent("item_LaserMod", null, new Texture2D(device, 1, 1));
            GlobalGameValues.Values.content.addContent("plasma_enemy", null, new Texture2D(device, 1, 1));
            GlobalGameValues.Values.content.addSound("missileExplosion", null);
        }
        //
        //Mit TestCleanup können Sie nach jedem einzelnen Test Code ausführen.
        [TestCleanup()]
        public void MyTestCleanup()
        {
            GlobalGameValues.Values.content = new ContentCollection();
        }

        #endregion


        internal virtual AIControlledAircraft_Drone CreateDroneController(out FabricatableAircraft owner, out FabricatableAircraft ship)
        {
            owner = CreateShip();
            ship = CreateShip();
            AIControlledAircraft_Drone controller = new AIControlledAircraft_Drone(owner, ship);
            return controller;
        }

        internal FabricatableAircraft CreateShip() 
        {
            Bounding bound = new Bounding(new Vector2(-400, -400), 800, 800, false);
            Matrix world =  Matrix.CreateWorld(new Vector3(0, 0, 0), Vector3.Backward, Vector3.Up);
            FabricatableAircraft ship = FabricatableAircraft.GET_ENEMY_1(world);
            ship.worldBounding = bound;
            return ship;
        }

        /// <summary>
        ///Ein Test für "executeAttackMode"
        ///</summary>
        [TestMethod()]
        public void executeAttackModeTest()
        {
            FabricatableAircraft owner;
            FabricatableAircraft ship;
            AIControlledAircraft_Drone controller = CreateDroneController(out owner, out ship);
            int updateRate = 166666;
            GlobalGameClasses.GlobalGameValues.Values.gameTime = new GameTime(new TimeSpan(updateRate), new TimeSpan(updateRate));
            WorldView.World world = new WorldView.World(new AchievementHandler(0, "SirTestington"), new WorldView.GenericDrawableList(), null, null);
            ship.world = world;
            ship.speed = 3;
            Vector3 trans = ship.worldMatrix.Translation;
            float x = trans.X;
            float y = trans.Z;
            controller.Update(DroneMode.ATTACK);
            ship.Update();
            Vector3 newTrans = ship.worldMatrix.Translation;
            float newX = newTrans.X;
            float newY = newTrans.Z;
            Assert.AreEqual(x, newX);
            Assert.AreNotEqual(y, newY);            
        }

        /// <summary>
        ///Ein Test für "executeDefendMode"
        ///</summary>
        [TestMethod()]
        public void executeDefendModeTest() {
            FabricatableAircraft owner;
            FabricatableAircraft ship;
            AIControlledAircraft_Drone controller = CreateDroneController(out owner, out ship);
            int updateRate = 166666;
            GlobalGameClasses.GlobalGameValues.Values.gameTime = new GameTime(new TimeSpan(updateRate), new TimeSpan(updateRate));
            ship.speed = 3;
            Vector3 trans = ship.worldMatrix.Translation;
            float z = trans.Z;
            controller.Update(DroneMode.DEFEND);
            ship.Update();
            Vector3 newTrans = ship.worldMatrix.Translation;
            float newZ = newTrans.Z;
            Assert.AreNotEqual(z, newZ);
        }
        
        /// <summary>
        ///Ein Test für "executeRepairMode"
        ///</summary>
        [TestMethod()]
        public void executeRepairModeTest() {
            FabricatableAircraft owner;
            FabricatableAircraft ship;
            AIControlledAircraft_Drone controller = CreateDroneController(out owner, out ship);
            owner.setPosition(new Vector2(2, 0));
            int updateRate = 166666;
            GlobalGameClasses.GlobalGameValues.Values.gameTime = new GameTime(new TimeSpan(updateRate), new TimeSpan(updateRate));
            ship.speed = 100;
            Vector3 trans = ship.worldMatrix.Translation;
            float y = trans.Z;
            controller.Update(DroneMode.REPAIR);
            ship.Update();
            Vector3 newTrans = ship.worldMatrix.Translation;
            float newX = newTrans.X;
            float newY = newTrans.Z;
            Assert.IsTrue(newX >= 2);
            Assert.AreNotEqual(newY, y);
        }
        
        /// <summary>
        ///Ein Test für "executeCollectMode"
        ///</summary>
        [TestMethod()]
        public void executeCollectModeTest() {
            int updateRate = 166666;
            GlobalGameClasses.GlobalGameValues.Values.gameTime = new GameTime(new TimeSpan(updateRate), new TimeSpan(updateRate));
            FabricatableAircraft owner;
            FabricatableAircraft ship;
            AIControlledAircraft_Drone controller = CreateDroneController(out owner, out ship);
            WorldView.World world = new WorldView.World(new AchievementHandler(0, "SirTestington"), new WorldView.GenericDrawableList(), null, null);
            ship.world = world;
            Vector3 trans = ship.worldMatrix.Translation;
            float y = trans.Z;
            ship.speed = 3;
            Item i = WeaponUpgrade.GET_DUMMY_UPGRADE();
            i.world = world;
            ship.world.addActor(i);
            i.setPosition(new Vector2(100, 100));
            controller.Update(DroneMode.COLLECT);
            ship.Update();
            Vector3 newTrans = ship.worldMatrix.Translation;
            float newY = newTrans.Z;
            Assert.AreNotEqual(y, newY);
        }
    }
}